package demo.mianshi.thread;

import java.util.concurrent.locks.Condition;
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;

public class _售票 {
    public static void main(String[] args) {
        // 一个出票一个售票线程，没有票时或售完后出票线程才开始生产，售票无票时需等待，有票就抢票直到空进行等待

        // 票据
        TicketInfo tk = new TicketInfo();
        // 卖票
        new Producter(tk).start();
        // 买票
        for (int i = 0; i < 100; i++) {
            new Consumer(tk).start();
        }
    }

    static class TicketInfo {
        private int max_count = 100;// 最大票数100
        private int availableTickets = 0;// 当前可用票数
        private Lock lock = new ReentrantLock();
        private Condition noTicket = lock.newCondition(); // 无票
        private Condition hasTicket = lock.newCondition();// 有票

        public void addTicket() {
            lock.lock();
            try {
                // 票满
                while (availableTickets >= max_count) {
                    System.out.println("票已满，等待出票");
                    noTicket.await();
                }
                // 出票10张
                for (int i = 1; i <= 100; i++) {
                    availableTickets++;
                    System.out.println(i + "新票，当前票数:" + availableTickets);
                    if (i % 10 == 0) {
                        hasTicket.signalAll(); // 每生产10张票就通知售票线程可以开始抢票
                    }
                }
                System.out.println("新票完成，当前票数:" + availableTickets);
                // 通知售票
                hasTicket.signalAll();
            } catch (InterruptedException e) {
                throw new RuntimeException(e);
            } finally {
                lock.unlock();
            }
        }

        public void saleTicket() {
            lock.lock();
            try {
                // 无票时等待
                while (availableTickets <= 0) {
                    System.out.println("无票，等待出票");
                    hasTicket.await();
                }
                // 有票抢票
                while (availableTickets > 0) {
                    availableTickets--;
                    System.out.println("出票1张,当前剩余票数:" + availableTickets);
                    if (availableTickets == 0) {
                        System.out.println("票已售完，等待新票");
                        noTicket.signal();
                    }
                }
            } catch (InterruptedException e) {
                throw new RuntimeException(e);
            } finally {
                lock.unlock();
            }
        }
    }

    static class Producter extends Thread {
        private final TicketInfo ticketInfo;

        Producter(TicketInfo ticketInfo) {
            this.ticketInfo = ticketInfo;
        }

        @Override
        public void run() {
            while (!Thread.interrupted()) {
                ticketInfo.addTicket();
                try {
                    Thread.sleep(500L);
                } catch (InterruptedException e) {
                    throw new RuntimeException(e);
                }
            }
        }
    }

    static class Consumer extends Thread {
        private final TicketInfo ticketInfo;

        Consumer(TicketInfo ticketInfo) {
            this.ticketInfo = ticketInfo;
        }

        @Override
        public void run() {
            while (!Thread.interrupted()) {
                ticketInfo.saleTicket();
                try {
                    Thread.sleep(100L);
                } catch (InterruptedException e) {
                    throw new RuntimeException(e);
                }
            }
        }
    }
}
